home *** CD-ROM | disk | FTP | other *** search
- /**\
- |**| µApp.c
- \**/
-
- /**\
- |**| ==============================================================================
- |**| COMPILER DIRECTIVES
- |**| ==============================================================================
- \**/
-
- #define kMaxTasks 64
-
- #define SystemSevenOrLater 1
- #define DEBUGSTRINGS 1
-
- /**\
- |**| ==============================================================================
- |**| INCLUDES
- |**| ==============================================================================
- \**/
-
- #ifndef USE_PRECOMPILED_HEADER
- #include "myHeaders.i"
- #endif
-
- #include <Devices.h>
- #include <Fonts.h>
- #include <CodeFragments.h>
- #include <Dialogs.h>
- #include <DiskInit.h>
- #include <LowMem.h>
- #include <Sound.h>
- #include <Traps.h>
- #include <Threads.h>
-
- #include <fp.h>
- #include <PLStringFuncs.h>
-
- #include <stdio.h>
- #include <string.h>
-
- #if __profile__
- #include <Profiler.h>
- #endif
-
- #include "CloseViewMP.h"
-
- /**\
- |**| ==============================================================================
- |**| TYPEDEFS, STRUCTS, DEFINES, ENUMS, ETC.
- |**| ==============================================================================
- \**/
-
- #if DEBUGSTRINGS
- # define DEBUGSTR(x) DebugStr((x))
- # define LOGSTRING(b,s) if (b) do {DEBUGSTR(s);} while (false);
- #else
- # define DEBUGSTR(x)
- # define LOGSTRING(b,s)
- #endif
-
- #define RECT_WIDTH(r) ((r).right - (r).left)
- #define RECT_HEIGHT(r) ((r).bottom - (r).top)
-
- #ifndef MIN
- # define ABS(x) ((x) >= 0 ? (x) : -(x))
- # define MIN(a,b) ((a) < (b) ? (a) : (b))
- # define MAX(a,b) ((a) > (b) ? (a) : (b))
- # define PIN(a,b,c) MIN(MAX((a),(b)),(c))
- #endif
-
- /**\
- |**| ==============================================================================
- |**| EXTERNAL FUNCTION PROTOTYPES
- |**| ==============================================================================
- \**/
-
- /**\
- |**| ==============================================================================
- |**| PRIVATE FUNCTION PROTOTYPES
- |**| ==============================================================================
- \**/
-
- static OSErr Init_Mac(void);
- static void Handle_Command(SInt32 ms);
- static void Handle_Event(const EventRecord *pEventPtr);
- static void Handle_NullEvent(const EventRecord *pEventPtr);
- static void Handle_MouseEvent(const EventRecord *pEventPtr);
- static void Handle_KeyEvent(char key,SInt16 modifiers);
- static void Handle_UpdateEvent(WindowPtr updateWindowP);
- static void Handle_ActivateEvent(WindowPtr updateWindowP);
- static void Handle_DiskEvent(SInt32 message);
- static void Handle_OSEvent(const EventRecord *pEventPtr);
- static void Handle_ContentClick(WindowPtr pWindowPtr,const EventRecord *pEventPtr);
-
- static Boolean SetUp_MenuBar(void);
- static void Adjust_MenuItems(void);
-
- static void DoZoomWindow(WindowPtr pWindowPtr, short zoomDir, short hMax, short vMax);
- static void DoGrowWindowGrid(WindowPtr pWindowPtr);
- static void DoDragWindowGrid(WindowPtr pWindowPtr, Point pPoint);
-
- /**\
- |**| ==============================================================================
- |**| PRIVATE GLOBALS
- |**| ==============================================================================
- \**/
-
- WindowPtr gWindowPtr = nil;
- Rect gWindowRect;
- Boolean gInBackGround = false;
- //Rect gMenuRect = {0,0,0,0};
- static Boolean gQuitFlag = false;
-
- static const RGBColor
- blackRGBColor = {0x0000,0x0000,0x0000},
- blueRGBColor = {0x0000,0x0000,0xFFFF},
- ltBlueRGBColor = {0x7FFF,0x7FFF,0xFFFF},
- dkBlueRGBColor = {0x0000,0x0000,0x7FFF},
- redRGBColor = {0xFFFF,0x0000,0x0000},
- greenRGBColor = {0x0000,0xFFFF,0x0000},
- yellowRGBColor = {0xFFFF,0xFFFF,0x0000},
- dkGrayRGBColor = {0x4444,0x4444,0x4444},
- whiteRGBColor = {0xFFFF,0xFFFF,0xFFFF};
-
- static RgnHandle gMouseRgnHdl = nil;
-
- static EventRecord gTheEvent; // from the main event loop
- static Boolean gHasColorQD = true;
- static Point gGridSize = {8,4};
-
- /**\
- |**| ==============================================================================
- |**| PRIVATE FUNCTIONS
- |**| ==============================================================================
- \**/
-
- void main(void)
- {
- #if __profile__
- if (!ProfilerInit(collectDetailed,bestTimeBase,20,5))
- {
- #endif
-
- if (!Init_Mac() && SetUp_MenuBar() && !CVMP_Init(1))
- {
- do
- {
- if (gMouseRgnHdl == nil)
- {
- Rect tRect = {-1,-1,1,1};
-
- gMouseRgnHdl = NewRgn();
- RectRgn(gMouseRgnHdl,&tRect);
- }
-
- InitCursor();
- WaitNextEvent(everyEvent,&gTheEvent,GetCaretTime(),gMouseRgnHdl);
- Handle_Event(&gTheEvent);
- }
- while (!gQuitFlag);
-
- CVMP_Term();
- }
- #if __profile__
- }
- ProfilerDump("\pµApp.dump");
- ProfilerTerm();
- #endif
- }
-
- /**\
- |**| Initialize toolboxes
- \**/
-
- static OSErr Init_Mac(void)
- {
- OSErr error;
- SysEnvRec theWorld;
-
- //
- // Test the computer to be sure we can do color.
- // If not we would crash, which would be bad.
- // If we can’t run, just beep and exit.
- //
-
- error = SysEnvirons(1, &theWorld);
- if (theWorld.hasColorQD == false)
- {
- SysBeep(50);
- ExitToShell(); // If no color QD, we must leave.
- }
-
- MaxApplZone();
- InitGraf(&(qd.thePort));
- InitFonts();
- InitWindows();
- InitMenus();
- TEInit();
- InitDialogs(nil);
-
- InitContextualMenus();
-
- //
- // Make a new window for drawing in, and it must be a color window.
- // The window is full screen size, made smaller to make it more visible.
- //
-
- gWindowRect = qd.screenBits.bounds;
- gWindowRect.top += LMGetMBarHeight() + 1;
-
- // make it 100x100
- InsetRect(&gWindowRect,
- (gWindowRect.right - gWindowRect.left - 100) >> 1,
- (gWindowRect.bottom - gWindowRect.top - 100) >> 1);
-
- gWindowPtr = NewCWindow(nil, &gWindowRect, "\pCloseViewMP!", true, zoomDocProc,
- (WindowPtr) -1, true, 0);
-
- if (gWindowPtr)
- gWindowRect = (*((WindowPeek) gWindowPtr)->contRgn)->rgnBBox;
-
- SetPort(gWindowPtr); // set window to current graf port
- TextSize(kTextSize); // smaller font for drawing.
-
- {
- short familyID;
- GetFNum("\pMonaco",&familyID);
- TextFont(familyID);
- }
-
- return noErr;
- }
-
- /**\
- |**| Menu hooks
- \**/
- #ifdef HellFrozenOver
- static pascal short MyMBarHook(Rect *menuRect)
- {
- // RgnHandle tempRgn = NewRgn();
-
- gMenuRect = *menuRect;
-
- // RectRgn(tempRgn,menuRect);
- // CalcVisBehind(LMGetWindowList(),tempRgn);
- // InvertRgn(tempRgn);
-
- //YieldToAnyThread();
- // DisposeRgn(tempRgn);
- return 0;
- }
-
- static pascal void MyMenuHook(void)
- {
- // RgnHandle tempRgn = NewRgn();
- // RectRgn(tempRgn,&gMenuRect);
- // CalcVisBehind(LMGetWindowList(),tempRgn);
- // InvertRgn(tempRgn);
-
- //YieldToAnyThread();
- // DisposeRgn(tempRgn);
- }
- #endif HellFrozenOver
-
- /**\
- |**| Setup menu bar
- \**/
-
- static Boolean SetUp_MenuBar(void)
- {
- Handle mBar = GetNewMBar(128); // handle to menu bar resource
- Boolean result = false;
-
- if (!ResError() && mBar)
- {
- SetMenuBar(mBar);
- AppendResMenu(GetMenuHandle(mAppleMenu),'DRVR');
- DrawMenuBar();
- ReleaseResource(mBar);
- Adjust_MenuItems();
-
- // LMSetMBarHook(NewMBarHookProc(MyMBarHook));
- // LMSetMenuHook(NewMenuHookProc(MyMenuHook));
-
- result = true;
- }
- return result;
- }
-
- /**\
- |**| Adjust menu items
- \**/
-
- static void Adjust_MenuItems(void)
- {
- MenuHandle tMenuHdl = GetMenuHandle(mMagMenu);
- if (tMenuHdl)
- {
- UInt16 index,count = CountMItems(tMenuHdl);
- for (index = 1;index <= count;index++)
- CheckItem(tMenuHdl, index, index == gMag);
- }
- }
-
- /**\
- |**| handle menu command
- \**/
-
- static void Handle_Command(SInt32 ms)
- {
- short menuID = ms >> 16,
- menuItem = ms & 0xFFFF;
-
- switch (menuID)
- {
- case mAppleMenu:
- switch (menuItem)
- {
- case iAboutBox: // Bring up alert for About.
- SysBeep(15);
- break;
- default: // All non-About items in this menu are DAs.
- {
- Str255 daName;
- GetMenuItemText(GetMenuHandle(menuID),menuItem,daName);
- OpenDeskAcc(daName);
- }
- break;
- }
- break;
- case mFileMenu:
- switch (menuItem)
- {
- case iQuit:
- gQuitFlag = true;
- break;
- default:
- SysBeep(15);
- break;
- }
- break;
- case mMagMenu:
- CVMP_SetMag(menuItem);
- break;
- case mWeightMenu: // Weight Menu
- CVMP_SetWeight(menuItem);
- break;
- }
- }
-
- /**\
- |**| handle event
- \**/
-
- static void Handle_Event(const EventRecord *pEventPtr)
- {
- switch (pEventPtr->what)
- {
- case nullEvent: // 0
- LOGSTRING(0,"\p|pHandle_Event-I-Debug, nullEvent.;g");
- Handle_NullEvent(pEventPtr);
- break;
- case mouseDown: // 1
- LOGSTRING(0,"\p|pHandle_Event-I-Debug, mouseDown.;g");
- Handle_MouseEvent(pEventPtr);
- break;
- case mouseUp: // 2
- LOGSTRING(0,"\p|pHandle_Event-I-Debug, mouseUp.;g");
- break;
- case keyDown: // 3
- LOGSTRING(0,"\p|pHandle_Event-I-Debug, keyDown.;g");
- goto dokey;
- case keyUp: // 4
- LOGSTRING(0,"\p|pHandle_Event-I-Debug, keyUp.;g");
- break;
- case autoKey: // 5
- LOGSTRING(0,"\p|pHandle_Event-I-Debug, autoKey.;g");
- dokey:
- Handle_KeyEvent((char)(pEventPtr->message & charCodeMask),pEventPtr->modifiers);
- case updateEvt: // 6
- LOGSTRING(0,"\p|pHandle_Event-I-Debug, updateEvt.;g");
- Handle_UpdateEvent((WindowPtr)pEventPtr->message);
- break;
- case diskEvt: // 7
- LOGSTRING(0,"\p|pHandle_Event-I-Debug, diskEvt.;g");
- Handle_DiskEvent(pEventPtr->message);
- break;
- case activateEvt: // 8
- LOGSTRING(0,"\p|pHandle_Event-I-Debug, activateEvt.;g");
- Handle_ActivateEvent((WindowPtr) pEventPtr->message);
- break;
- case osEvt: // 15
- LOGSTRING(0,"\p|pHandle_Event-I-Debug, osEvt.;g");
- Handle_OSEvent(pEventPtr);
- break;
- case kHighLevelEvent: // 23
- LOGSTRING(0,"\p|pHandle_Event-I-Debug, kHighLevelEvent.;g");
- AEProcessAppleEvent(pEventPtr);
- break;
- default:
- DEBUGSTR("\p|pHandle_Event-I-Debug, UnHandled Event.;g");
- break;
- }
- }
-
- /**\
- |**| handle null event
- \**/
-
- static void Handle_NullEvent(const EventRecord *pEventPtr)
- {
- (pEventPtr); // #pragma unused (pEventPtr)
- if (gWindowPtr)
- {
- Rect tRect = {40,20,52,128};
- const RGBColor blackRGBColor = {0,0,0}, yellowRGBColor = {255,255,0};
- GrafPtr savePort;
-
- GetPort(&savePort);
- SetPort(gWindowPtr);
-
- gWindowRect = (*((WindowPeek) gWindowPtr)->contRgn)->rgnBBox;
-
- CVMP_DoNull();
-
- SetPort(savePort);
- }
- }
-
- /**\
- |**| handle mousedown event
- \**/
-
- static void Handle_MouseEvent(const EventRecord *pEventPtr)
- {
- WindowPtr window;
- short part;
-
- CVMP_Update(); // Force a demand refresh to give that smooth look.
-
- part = FindWindow(pEventPtr->where,&window);
-
- if (part != inContent)
- SetCursor(&qd.arrow);
-
- switch(part)
- {
- case inContent:
- Handle_ContentClick(window,pEventPtr);
- break;
-
- case inDrag:
- CVMP_Pause(true);
- DoDragWindowGrid(window, pEventPtr->where);
- break;
-
- case inGoAway:
- if (TrackGoAway(window,pEventPtr->where))
- {
- CVMP_Pause(true);
- DisposeWindow(window);
- if (window == gWindowPtr)
- gWindowPtr = nil;
- }
- break;
-
- case inGrow:
- CVMP_Pause(true);
- DoGrowWindowGrid(window);
- break;
-
- case inMenuBar: // Process mouse menu command (if any).
- {
- SInt32 ms;
-
- Adjust_MenuItems();
- ms = MenuSelect(pEventPtr->where);
- if (ms)
- Handle_Command(ms);
- HiliteMenu(0); // Unhighlight what MenuSelect hilited.
- }
- break;
-
- case inSysWindow: // Let the system handle the mouseDown.
- SystemClick(pEventPtr,window);
- break;
-
- case inZoomIn:
- case inZoomOut:
- {
- Rect zoomLimits = qd.screenBits.bounds;
-
- CVMP_Pause(true);
- DoZoomWindow(window, part,
- RECT_WIDTH(zoomLimits),
- RECT_HEIGHT(zoomLimits));
- }
- break;
-
- default:
- break;
- }
- if (gWindowPtr)
- gWindowRect = (*((WindowPeek) gWindowPtr)->contRgn)->rgnBBox;
-
- // SetRect(&gMenuRect, 0, 0, 0, 0);
- }
-
- /**\
- |**| handle key events
- \**/
-
- static void Handle_KeyEvent(char key,SInt16 modifiers)
- {
- if ((modifiers & cmdKey) != 0)
- {
- Adjust_MenuItems();
- Handle_Command(MenuKey(key));
- HiliteMenu(0); // Unhighlight what MenuSelect hilited.
- }
- }
-
- /**\
- |**| handle update events
- \**/
-
- static void Handle_UpdateEvent(WindowPtr updateWindowP)
- {
- GrafPtr savePort;
-
- GetPort(&savePort);
- SetPort(updateWindowP);
- BeginUpdate(updateWindowP);
-
- if (updateWindowP == gWindowPtr)
- {
-
- }
- #ifdef HellFrozenOver
- DrawControls(updateWindowP);
- #else
- UpdateControls(updateWindowP,updateWindowP->visRgn);
- #endif
- DrawGrowIcon(updateWindowP);
- EndUpdate(updateWindowP);
-
- SetPort(savePort);
- }
-
- /**\
- |**| handle disk events
- \**/
-
- static void Handle_DiskEvent(SInt32 message)
- {
- Point dialogLocation = {100,100};
-
- if ((message & 0xFFFF0000) != noErr)
- {
- DIBadMount(dialogLocation,message);
- }
- }
-
- /**\
- |**| handle Activate events
- \**/
-
- static void Handle_ActivateEvent(WindowPtr updateWindowP)
- {
- #pragma unused(updateWindowP)
- }
-
- /**\
- |**| handle OS events
- \**/
-
- static void Handle_OSEvent(const EventRecord *pEventPtr)
- {
- UInt32 message = pEventPtr->message;
- if ((message >> 24) == suspendResumeMessage)
- {
- LOGSTRING(0,"\p|Handle_OSEvent-I-Debug, suspendResumeMessage.;g");
- if ((message & resumeFlag) != 0)
- gInBackGround = false;
- else
- gInBackGround = true;
- }
- else if ((message >> 24) == mouseMovedMessage)
- {
- Rect tRect = {-1,-1,1,1};
-
- LOGSTRING(0,"\p|Handle_OSEvent-I-Debug, mouseMovedMessage.;g");
-
- OffsetRect(&tRect,pEventPtr->where.h,pEventPtr->where.v);
- RectRgn(gMouseRgnHdl,&tRect);
- CVMP_SetMidPoint(pEventPtr->where);
- CVMP_Update(); // Tickle the blit task.
- }
- }
-
- /**\
- |**| handle mouse down in window content
- \**/
-
- static void Handle_ContentClick(WindowPtr pWindowPtr,const EventRecord *pEventPtr)
- {
- #pragma unused (pEventPtr)
- if (pWindowPtr != FrontWindow())
- SelectWindow(pWindowPtr);
- else
- CVMP_DoClick(pEventPtr);
- }
-
- /**\
- |**| return the rectangle for the screen that contains the most of the rectangle
- \**/
-
- static Rect GetMajorScreenRect(Rect *pRectPtr)
- {
- Rect result;
- GDHandle dominantGDevice = nil;
-
- /*
- * Color QuickDraw implies the possibility of multiple monitors.
- * One should move the rect onto the monitor containing the greatest
- * portion of the rect. This requires walking the gDevice list.
- */
-
- if (gHasColorQD)
- {
- Rect theSect;
- GDHandle nthDevice;
- long sectArea, greatestArea;
-
- greatestArea = 0;
- for (nthDevice = DMGetFirstScreenDevice(true);nthDevice;
- nthDevice = DMGetNextScreenDevice(nthDevice,true))
- {
- SectRect(pRectPtr, &(**nthDevice).gdRect, &theSect);
- sectArea = (long) RECT_WIDTH(theSect) * (long) RECT_HEIGHT(theSect);
- if (sectArea > greatestArea) {
- greatestArea = sectArea; // save the greatest intersection
- dominantGDevice = nthDevice; // and which device it belongs to
- }
- }
- }
-
- /*
- * At this point, we know the dimensions of our rectangle, and we know
- * what screen we're going to put it on. To be more specific, however, we need a
- * rectangle which defines the maximum dimensions of the rectangle.
- *
- * This rectangle accounts for the thickness of the window frame, the menu bar, and
- * one or two pixels around the edges for cosmetic reasons.
- */
-
- if (dominantGDevice != nil)
- {
- result = (**dominantGDevice).gdRect;
- if (dominantGDevice == GetMainDevice()) // account for menu bar on main device
- result.top += GetMBarHeight();
- }
- else
- {
- result = qd.screenBits.bounds; // if no gDevice, use default monitor
- result.top += GetMBarHeight();
- }
-
- return result;
- }
-
- /**\
- |**| Pin the first rect into the second
- \**/
-
- static void PinRectInRect(Rect *pRect1,const Rect *pRect2)
- {
- if (pRect1->left < pRect2->left)
- {
- OffsetRect(pRect1,pRect2->left - pRect1->left,0);
- if (pRect1->right > pRect2->right)
- pRect1->right = pRect2->right;
- }
- else if (pRect1->right > pRect2->right)
- {
- OffsetRect(pRect1,pRect2->right - pRect1->right,0);
- if (pRect1->left < pRect2->left)
- pRect1->left = pRect2->left;
- }
-
- if (pRect1->top < pRect2->top)
- {
- OffsetRect(pRect1,0,pRect2->top - pRect1->top);
- if (pRect1->bottom > pRect2->bottom)
- pRect1->bottom = pRect2->bottom;
- }
- else if (pRect1->bottom > pRect2->bottom)
- {
- OffsetRect(pRect1,0,pRect2->bottom - pRect1->bottom);
- if (pRect1->top < pRect2->top)
- pRect1->top = pRect2->top;
- }
- }
-
- /**\
- |**| DoZoomWindow
- \**/
-
- static void DoZoomWindow(WindowPtr pWindowPtr, short zoomDir, short hMax, short vMax)
- {
- Rect *zoomRect;
- Rect globalPortRect, dGDRect;
-
- if (TrackBox(pWindowPtr, gTheEvent.where, zoomDir))
- {
- SetPort(pWindowPtr);
- EraseRect(&pWindowPtr->portRect); // recommended for cosmetic reasons
-
- if (zoomDir == inZoomOut)
- {
- /*
- * ZoomWindow() is a good basic tool, but it doesn't do everything necessary to
- * implement a good human interface when zooming. In fact it's not even close for
- * more high-end hardware configurations. We must help it along by calculating an
- * appropriate window size and location any time a window zooms out.
- */
-
- zoomRect = &(*((WindowPeek) pWindowPtr)->strucRgn)->rgnBBox;
- dGDRect = GetMajorScreenRect(zoomRect);
-
- globalPortRect = pWindowPtr->portRect;
- LocalToGlobal(&topLeft(globalPortRect)); // calculate the window's portRect
- LocalToGlobal(&botRight(globalPortRect)); // in global coordinates
-
- // account for the window frame and inset it a few pixels
- dGDRect.left += 2 + globalPortRect.left - zoomRect->left;
- dGDRect.top += 2 + globalPortRect.top - zoomRect->top;
- dGDRect.right -= 1 + zoomRect->right - globalPortRect.right;
- dGDRect.bottom -= 1 + zoomRect->bottom - globalPortRect.bottom;
-
- /*
- * Now we know exactly what our limits are, and since there are input parameters
- * specifying the dimensions we'd like to see, we can move and resize the zoom
- * state rectangle for the best possible results. We have three goals in this:
- * 1. Display the window entirely visible on a single device.
- * 2. Resize the window to best represent the dimensions of the document itself.
- * 3. Move the window as short a distance as possible to achieve #1 and #2.
- */
-
- zoomRect = &(**(WStateDataHandle) ((WindowPeek) pWindowPtr)->dataHandle).stdState;
-
- /*
- * Initially set the zoom rectangle to the size requested by the input parameters,
- * although not smaller than a minimum size. We do this without moving the origin.
- */
-
- zoomRect->right = (zoomRect->left = globalPortRect.left) + hMax;
- // MAX(hMax, MinWindowWidth(pWindowPtr));
- zoomRect->bottom = (zoomRect->top = globalPortRect.top) + vMax;
- // MAX(vMax, MinWindowHeight(pWindowPtr));
-
- // Shift the entire rectangle if necessary to bring its origin inside dGDRect.
- OffsetRect(zoomRect,
- MAX(dGDRect.left - zoomRect->left, 0),
- MAX(dGDRect.top - zoomRect->top, 0));
-
- /*
- * Shift the rectangle up and/or to the left if necessary to accomodate the view,
- * and if it is possible to do so. The rectangle may not be moved such that its
- * origin would fall outside of dGDRect.
- */
-
- OffsetRect(zoomRect,
- -PIN(zoomRect->right - dGDRect.right, 0, zoomRect->left - dGDRect.left),
- -PIN(zoomRect->bottom - dGDRect.bottom, 0, zoomRect->top - dGDRect.top));
-
- // Clip expansion to dGDRect, in case view is larger than dGDRect.
- zoomRect->right = MIN(zoomRect->right, dGDRect.right);
- zoomRect->bottom = MIN(zoomRect->bottom, dGDRect.bottom);
- }
- ZoomWindow(pWindowPtr, zoomDir, false); // all it needed was a brain transplant
- }
- } // DoZoomWindow
-
- /**\
- |**| DoGrowWindowGrid
- \**/
-
- #define kExtremeNeg -32768
- #define kExtremePos (32767 - 1) /* required to address an old region bug, see develop 20 Q&As */
-
- static void PullRect(Rect* startRect); // prototype
- static void DoGrowWindowGrid(WindowPtr pWindowPtr)
- {
- PenState oldPen;
- WindowPtr tempWP, WMPort;
- Rect draggingRect = pWindowPtr->portRect;
- Rect wideOpen = {kExtremeNeg, kExtremeNeg, kExtremePos, kExtremePos};
- RgnHandle oldRgn = NewRgn();
-
- GetPort(&tempWP);
- SetPort(pWindowPtr);
-
- /* normalize my rectangle into the window manager port coordinates */
- LocalToGlobal((Point *) &draggingRect.top);
- LocalToGlobal((Point *) &draggingRect.bottom);
-
- /* go to the WManager port */
- GetWMgrPort(&WMPort);
- SetPort(WMPort);
-
- /* save the Window manager pen state since we'll be changing it */
- GetPenState(&oldPen);
-
- /* localize back */
- GlobalToLocal((Point *) &draggingRect.top);
- GlobalToLocal((Point *) &draggingRect.bottom);
-
- /* save the current clip region, and set our wide-open clip */
- GetClip(oldRgn);
- ClipRect(&wideOpen);
-
- /* go to the routine below to do the actual dragging */
- PullRect(&draggingRect);
-
- /* restore the original environment */
- SetClip(oldRgn);
- SetPenState(&oldPen);
- DisposeRgn(oldRgn);
-
- /* now size the window for the returned rect */
- SetPort(pWindowPtr);
- InvalRect(&pWindowPtr->portRect);
-
- {
- Rect tRect = GetMajorScreenRect(&(*((WindowPeek) pWindowPtr)->contRgn)->rgnBBox);
- PinRectInRect(&draggingRect,&tRect);
- MoveWindow(pWindowPtr,draggingRect.left,draggingRect.top,true);
- }
-
- SizeWindow(pWindowPtr, draggingRect.right - draggingRect.left, draggingRect.bottom - draggingRect.top, true);
- SetPort(tempWP);
- } // DoGrowWindowGrid
-
- static void PullRect(Rect* startRect)
- {
- Rect oldRect;
- Point endPoint;
- Boolean hreversed = false;
- Boolean vreversed = false;
- short tempH,tempV;
- short divByGridh,divByGridv;
-
- /* set up */
- oldRect = *startRect;
- PenMode(srcXor); /* So we can rubberband */
- PenPat(&qd.gray);
- FrameRect(startRect);
- divByGridh = startRect->right;
- divByGridv = startRect->bottom;
-
- while (StillDown())
- { /* Keep doing this as long as the */
- /* user keeps the mouse down */
-
- GetMouse(&endPoint); /* Current mouse position in local */
-
- // see if it's on a grid point
- tempH = ABS(endPoint.h - divByGridh) / gGridSize.h;
- tempV = ABS(endPoint.v - divByGridv) / gGridSize.v;
-
- // normalize to our grid values. We'll always go outwards as better
- if ((tempH * gGridSize.h) != ABS(endPoint.h - divByGridh)) // shove out based on the remainer
- endPoint.h = (((endPoint.h) / gGridSize.h) * gGridSize.h) + gGridSize.h;
- if ((tempV * gGridSize.v) != ABS(endPoint.v - divByGridv))
- endPoint.v = (((endPoint.v) / gGridSize.v) * gGridSize.v) + gGridSize.v;
-
- // If things reversed, we have to make sure that we don't try
- // and grid the origin point of the drag, cuz that would be weird
- if (hreversed)
- { /* see if the rectangle flipped first */
- if (endPoint.h > startRect->right) /* they flipped back */
- hreversed = false; /* and ignore this move */
- else /* still reversed */
- startRect->left = endPoint.h;
- }
- else
- {
- if (endPoint.h < startRect->left)
- hreversed = true;
- else
- startRect->right = endPoint.h;
- }
- if (vreversed)
- { /* see if it flipped first */
- if (endPoint.v > startRect->bottom) /* they flipped back */
- vreversed = false; /* and ignore this move */
- else /* still reversed */
- startRect->top = endPoint.v;
- }
- else
- {
- if (endPoint.v < startRect->top)
- vreversed = true;
- else
- startRect->bottom = endPoint.v;
- }
-
- if (!EqualRect(startRect,&oldRect))
- { /* redraw the rect only if the mouse moved */
- FrameRect(&oldRect);
- FrameRect(startRect); /* draw the new rect */
- oldRect = *startRect;
- }
- }
- FrameRect(startRect);
-
- PenMode(srcCopy);
- PenPat(&qd.black);
- } // PullRect
-
-
- /*-------------------------------------------------------------------------------------
-
- DoDragWindowGrid- a big nasty function to Drag a window along grid lines.
- Note the elegant error handling. You should change it to make your users happy.
-
- You can change the size of the 'grid rects' by changing the value of kIncrement.
-
- */
- static void DoDragWindowGrid(WindowPtr pWindowPtr, Point pPoint)
- {
- RgnHandle dragRgn, lastDragRgn, insetGray;
- GrafPtr oldPort, tmpPort;
- Point currPt, firstMulPoint, lastMulPoint, currMulPoint;
- Boolean frameHidden;
- enum {kIncrement = 16, kBorderInset = 4};
-
- // Set up our regions - init our variables.
- dragRgn = NewRgn();
- lastDragRgn = NewRgn();
- insetGray = NewRgn();
- if ((dragRgn == NULL) || (lastDragRgn == NULL) || (insetGray == NULL)) {
- DebugStr("\pnot enough memory- bye!");
- return;
- }
- CopyRgn(GetGrayRgn(), insetGray);
- if (MemError() != noErr) {
- DebugStr("\pnot enough memory- bye!");
- return;
- }
-
- InsetRgn(insetGray, kBorderInset, kBorderInset);
- frameHidden = false;
-
- // Set up a port to draw into, and save off the old
- tmpPort = (GrafPtr)NewPtr(sizeof(GrafPort));
- if (tmpPort == NULL) {
- DebugStr("\pnot enough memory- bye!");
- return;
- }
- GetPort(&oldPort);
- OpenPort(tmpPort);
- CopyRgn(GetGrayRgn(), tmpPort->visRgn);
- if (MemError() != noErr) {
- DebugStr("\pnot enough memory- bye!");
- return;
- }
- tmpPort->portRect = (*GetGrayRgn())->rgnBBox;
- SetPort(tmpPort);
-
- PenMode(patXor);
- PenPat(&qd.gray);
-
- // Set the incoming point to be on a multiple of kIncrement,
- // to make later calculations easier.
- currMulPoint.h = pPoint.h + (kIncrement/2);
- currMulPoint.h /= kIncrement; currMulPoint.h *= kIncrement;
- currMulPoint.v = pPoint.v + (kIncrement/2);
- currMulPoint.v /= kIncrement; currMulPoint.v *= kIncrement;
-
- firstMulPoint = lastMulPoint = currMulPoint;
-
- CopyRgn(((WindowPeek)pWindowPtr)->strucRgn, dragRgn);
- if (MemError() != noErr) {
- DebugStr("\pnot enough memory- bye!");
- return;
- }
-
- CopyRgn(((WindowPeek)pWindowPtr)->strucRgn, lastDragRgn);
- if (MemError() != noErr) {
- DebugStr("\pnot enough memory- bye!");
- return;
- }
-
- // Draw the first framed region, which will follow the mouse
- // on the screen
- FrameRgn(lastDragRgn);
-
- while (WaitMouseUp() == true) {
- // Now track the mouse, and when it moves enough make the framed
- // region move as well.
- GetMouse(&currPt);
-
- // Set the new point to be on a multiple of kIncrement
- currMulPoint.h = currPt.h + (kIncrement/2);
- currMulPoint.h /= kIncrement; currMulPoint.h *= kIncrement;
- currMulPoint.v = currPt.v + (kIncrement/2);
- currMulPoint.v /= kIncrement; currMulPoint.v *= kIncrement;
-
- // Should we be showing the frame region ??
- if (PtInRgn(currPt, insetGray) == false) {
- // It's somewhere near the edges, so hide the frame
- if (frameHidden == false) // if it's not hidden already, hide it now
- FrameRgn(lastDragRgn);
- frameHidden = true;
- }
- else { // else, the frame should be shown if it's hidden
- if (frameHidden == true) {
- FrameRgn(lastDragRgn);
- frameHidden = false;
- }
- }
-
- // Has the mouse moved ?
- if (!EqualPt(currMulPoint,lastMulPoint)) {
- // The mouse coordinates have changed enough to adjust the window,
- // so move the frame accordingly
- OffsetRgn(dragRgn, currMulPoint.h - lastMulPoint.h, currMulPoint.v - lastMulPoint.v);
-
- if (frameHidden == false) {
- // Only show the frame if we're allowed to.
- FrameRgn(dragRgn);
- FrameRgn(lastDragRgn);
- }
- lastMulPoint = currMulPoint;
- CopyRgn(dragRgn, lastDragRgn);
- if (MemError() != noErr) {
- DebugStr("\pnot enough memory- bye!");
- return;
- }
- }
- }
-
- // If frameHidden is true, there's no need to erase the final frame.
- if (frameHidden == false)
- FrameRgn(lastDragRgn);
-
- if (!EqualPt(lastMulPoint,firstMulPoint) && (frameHidden == false)) {
- // The mouse has moved from its original position and is
- // somewhere on the screen, so move the window accordingly.
- Point globalPt, diffPt, contPt = {0, 0};
-
- // Calculate the difference between the strucRgn's 0, 0 and
- // the window's content region 0, 0. Remember that MoveWindow
- // moves the window's *content* to the coordinate specified, and
- // we want to move the window's structure to fit in the lastDragRgn
- SetPort(pWindowPtr);
- // LocalToGlobal works much better when the port is set up...
- LocalToGlobal(&contPt);
- SetPort(tmpPort);
- diffPt.h = contPt.h - (*((WindowPeek)pWindowPtr)->strucRgn)->rgnBBox.left;
- diffPt.v = contPt.v - (*((WindowPeek)pWindowPtr)->strucRgn)->rgnBBox.top;
-
- globalPt.h = (*lastDragRgn)->rgnBBox.left;
- globalPt.v = (*lastDragRgn)->rgnBBox.top;
- LocalToGlobal(&globalPt);
- globalPt.h += diffPt.h;
- globalPt.v += diffPt.v;
- MoveWindow(pWindowPtr, globalPt.h, globalPt.v, true);
- }
-
- {
- Rect wRect = (*((WindowPeek) pWindowPtr)->contRgn)->rgnBBox;
- Rect tRect = GetMajorScreenRect(&wRect);
- PinRectInRect(&wRect,&tRect);
- MoveWindow(pWindowPtr,wRect.left,wRect.top,true);
- // SizeWindow(pWindowPtr, wRect.right - wRect.left, wRect.bottom - wRect.top, true);
- }
-
- // Close the port and tear everything down
- ClosePort(tmpPort);
- SetPort(oldPort);
- DisposeRgn(dragRgn);
- DisposeRgn(insetGray);
- DisposeRgn(lastDragRgn);
- } // DoDragWindowGrid
-